using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Tilemaps;
using System.IO;
using System.Text;

public class Online : MonoBehaviour
{
    public Tilemap map;
    public Button btn;
    public Vector3Int start;
    public Vector3Int end;
    private Hashtable table;
    private string[] index;
    private string[] database;
    private string filepath1;
    private string filepath2;
    private string filepath3;
    private string filepath4;

    // Start is called before the first frame update
    void Start()
    {
        start = new Vector3Int(-44, -43, 0);
        end = new Vector3Int(-15, -33, 0);
        filepath1 = @"C:\Users\caomb\Desktop\实训\索引.txt";
        string[] lines = File.ReadAllLines(filepath1);
        table = new Hashtable();
        for(int i = 0; i < lines.Length; i++) {
            string[] tmp = lines[i].Split();
            table.Add(tmp[0], tmp[1]);
        }
        filepath2 = @"C:\Users\caomb\Desktop\实训\数据库索引.txt";
        index = File.ReadAllLines(filepath2);
        filepath3 = @"C:\Users\caomb\Desktop\实训\压缩数据库.txt";
        database = File.ReadAllLines(filepath3);
        filepath4 = @"C:\Users\caomb\Desktop\实训\测试路径.txt";
        btn.onClick.AddListener(foo);
    }

    void foo()
    {
        int boundX = map.cellBounds.x;
        int boundY = map.cellBounds.y;
        int sizeX = map.cellBounds.size.x;
        int id1 = (start.y - boundY) * sizeX + (start.x - boundX);
        int id2 = (end.y - boundY) * sizeX + (end.x - boundX);
        int region1 = (int)Convert.ToDouble((string)table[Convert.ToString(id1)]);
        int region2 = (int)Convert.ToDouble((string)table[Convert.ToString(id2)]);
        string[] tmp = index[region1].Split();
        int row = (int)Convert.ToDouble(tmp[region2]);
        string[] path = database[row*2-1].Split();
        ArrayList _path = new ArrayList();
        Vector3Int p1 = start;
        _path.Add(p1);
        Vector3Int p2 = ConvertToPoint(path[0]);
        for(int i = 0; i <= path.Length; i++) {
            HillClimbing(p1, p2, _path);
            if(i != path.Length) {
                p1 = p2;
                if(i == path.Length-1) {
                    p2 = end;
                } else {
                    p2 = ConvertToPoint(path[i+1]);
                }
            }
        }
        using(StreamWriter sw = new StreamWriter(filepath4, false)) {
            for(int i = 0; i < _path.Count; i++) {
                Vector3Int p = (Vector3Int)_path[i];
                sw.WriteLine(p.x + " " + p.y);
            }
        }
    }

    Vector3Int ConvertToPoint(string p) {
        char[] separator = {'(', ',', ')'};
        string[] _p = p.Split(separator);
        int x = (int)Convert.ToDouble(_p[1]);
        int y = (int)Convert.ToDouble(_p[2]);
        Vector3Int vp = new Vector3Int(x, y, 0);
        return vp;
    }

    void HillClimbing(Vector3Int p1, Vector3Int p2, ArrayList path) {
        Vector3Int _start = p1;
        Vector3Int _end = p2;
        if(_start == _end) {
            return;
        }
        while(_start != _end) {
            ArrayList list = new ArrayList();
            Vector3Int next = _start;
            double f = 999999;
            for(int i = -1; i <= 1; i++) {
                for(int j = -1; j <= 1; j++) {
                    Vector3Int p = new Vector3Int(_start.x+i, _start.y+j, 0);
                    if(map.HasTile(p)) {
                        list.Add(p);
                    }
                }
            }
            int offsetX = Math.Abs(_end.x - _start.x);
            int offsetY = Math.Abs(_end.y - _start.y);
            double square = offsetX * offsetX + offsetY * offsetY;
            double current_h = Math.Pow(square, 0.5);
            for(int i = 0; i < list.Count; i++) {
                Vector3Int p = (Vector3Int)list[i];
                offsetX = Math.Abs(_start.x - p.x);
                offsetY = Math.Abs(_start.y - p.y);
                square = offsetX * offsetX + offsetY * offsetY;
                double g = Math.Pow(square, 0.5);
                offsetX = Math.Abs(_end.x - p.x);
                offsetY = Math.Abs(_end.y - p.y);
                square = offsetX * offsetX + offsetY * offsetY;
                double h = Math.Pow(square, 0.5);
                if(current_h > h && f > g + h) {
                    next = p;
                    f = g + h;
                }
            }
            if(_start == next) {
                if(_start != _end) {
                    Debug.Log("Error");
                }
                break;
            } else {
                _start = next;
                path.Add(next);
            }
        }
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}
